﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using System.Xml;

namespace SuperX.Common.Helper
{
    /// <summary>
    /// 序列化工具
    /// </summary>    
    public class SerializerUtil
    {
        /// <summary>
        /// 序列化BIN
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filePath"></param>
        /// <param name="t"></param>
        public static string Serialize<T>(T obj)
        {
            StringWriter stringWriter = null;
            string result;
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
                stringWriter = new StringWriter();
                xmlSerializer.Serialize(stringWriter, obj);
                stringWriter.Flush();
                result = stringWriter.ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (stringWriter != null)
                {
                    stringWriter.Close();
                    stringWriter.Dispose();
                }
            }
            return result;
        }

        // 
        public static string Serialize<T>(T obj, Type[] extraTypes)
        {
            StringWriter stringWriter = null;
            string result;
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), extraTypes);
                stringWriter = new StringWriter();
                xmlSerializer.Serialize(stringWriter, obj);
                stringWriter.Flush();
                result = stringWriter.ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (stringWriter != null)
                {
                    stringWriter.Close();
                    stringWriter.Dispose();
                }
            }
            return result;
        }

        // 
        public static void Serialize<T>(T obj, XmlWriter writer)
        {
            new XmlSerializer(typeof(T)).Serialize(writer, obj);
        }

        // 
        public static void Serialize<T>(T obj, XmlWriter writer, Type[] extraTypes)
        {
            new XmlSerializer(typeof(T), extraTypes).Serialize(writer, obj);
        }

        // 
        public static T Deserialize<T>(XmlReader reader)
        {
            return (T)((object)new XmlSerializer(typeof(T)).Deserialize(reader));
        }

        // 
        public static T Deserialize<T>(XmlReader reader, Type[] extraTypes)
        {
            return (T)((object)new XmlSerializer(typeof(T), extraTypes).Deserialize(reader));
        }

        // 
        public static T Deserialize<T>(string xml)
        {
            T result;
            if (xml == null || xml == string.Empty)
            {
                result = default(T);
                return result;
            }
            StringReader stringReader = null;
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
                stringReader = new StringReader(xml);
                result = (T)((object)xmlSerializer.Deserialize(stringReader));
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (stringReader != null)
                {
                    stringReader.Close();
                    stringReader.Dispose();
                }
            }
            return result;
        }

        // 
        public static T Deserialize<T>(string xml, Type[] extraTypes)
        {
            T result;
            if (string.IsNullOrEmpty(xml))
            {
                result = default(T);
                return result;
            }
            StringReader stringReader = null;
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), extraTypes);
                stringReader = new StringReader(xml);
                result = (T)((object)xmlSerializer.Deserialize(stringReader));
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (stringReader != null)
                {
                    stringReader.Close();
                    stringReader.Dispose();
                }
            }
            return result;
        }

        // 
        public static void SaveAs<T>(T obj, string fileName, Encoding encoding, Type[] extraTypes)
        {
            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }
            DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(fileName));
            if (!directoryInfo.Exists)
            {
                directoryInfo.Create();
            }
            XmlDocument xmlDocument = new XmlDocument();
            using (XmlWriter xmlWriter = XmlWriter.Create(fileName, new XmlWriterSettings
            {
                Indent = true,
                Encoding = encoding,
                CloseOutput = true,
                CheckCharacters = false
            }))
            {
                if (extraTypes != null)
                {
                    SerializerUtil.Serialize<T>(obj, xmlWriter, extraTypes);
                }
                else
                {
                    SerializerUtil.Serialize<T>(obj, xmlWriter);
                }
                xmlWriter.Flush();
                xmlDocument.Save(xmlWriter);
            }
        }

        // 
        public static void SaveAs<T>(T obj, string fileName, Type[] extraTypes)
        {
            SerializerUtil.SaveAs<T>(obj, fileName, Encoding.UTF8, extraTypes);
        }

        // 
        public static void SaveAs<T>(T obj, string fileName, Encoding encoding)
        {
            SerializerUtil.SaveAs<T>(obj, fileName, encoding, null);
        }

        // 
        public static void SaveAs<T>(T obj, string fileName)
        {
            SerializerUtil.SaveAs<T>(obj, fileName, Encoding.UTF8);
        }

        // 
        public static T Open<T>(string fileName, Type[] extraTypes)
        {
            T result = default(T);
            if (File.Exists(fileName))
            {
                using (XmlReader xmlReader = XmlReader.Create(fileName, new XmlReaderSettings
                {
                    CloseInput = true,
                    CheckCharacters = false
                }))
                {
                    xmlReader.ReadOuterXml();
                    if (extraTypes != null)
                    {
                        result = SerializerUtil.Deserialize<T>(xmlReader, extraTypes);
                    }
                    else
                    {
                        result = SerializerUtil.Deserialize<T>(xmlReader);
                    }
                }
            }
            return result;
        }

        // 
        public static T Open<T>(string fileName)
        {
            return SerializerUtil.Open<T>(fileName, null);
        }
    }
}
